在控制流中§

有关 gather/take 的主要文档,请参阅 in context

gather 是一个语句或块前缀,它返回一个值 序列。这些值来自对 gather 代码的动态作用域中 take 的调用。在以下示例中,我们使用 gather 实现了一个子例程来计算整数的因子(请注意,这些因子不是按顺序生成的)

sub factorsInt:D \n ) {
    my $k = 1;
    gather {
        while $k**2 < n {
            if n %% $k {
                take $k;
                take n div $k;
            }
            $k++;
        }
        take $k if $k**2 == n;
    }
}
 
say factors(36); # OUTPUT: «1, 36, 2, 18, 3, 12, 4, 9, 6␤»

gather/take 组合可以根据上下文生成惰性值。绑定到标量或无 sigil 容器将强制惰性。如果您想强制进行惰性求值,请使用 lazy 子例程或方法。例如

my @vals = lazy gather {
    take 1;
    say "Produced a value";
    take 2;
}
say @vals[0];
say 'between consumption of two values';
say @vals[1];
 
# OUTPUT: 
# 1 
# between consumption of two values 
# Produced a value 
# 2

gather/take 是动态作用域的,因此您可以从 gather 中调用的子例程或方法中调用 take

sub weird(@elems:$direction = 'forward'{
    my %direction = (
        forward  => sub { take $_ for @elems },
        backward => sub { take $_ for @elems.reverse },
        random   => sub { take $_ for @elems.pick(*},
    );
    return gather %direction{$direction}();
}
 
say weird(<a b c>:direction<backward> );          # OUTPUT: «(c b a)␤»

如果值需要在调用方是可变的,请使用 take-rw

请注意,由 gather/take 创建的 Seq 可能会被强制转换为另一种类型。一个分配给哈希的示例

my %h = gather { take "foo" => 1take "bar" => 2};
say %h;                   # OUTPUT: «{bar => 2, foo => 1}␤»

注意gather/take 不得用于收集 react/whenever 的结果。whenever 块不是由运行 gather/react 的线程运行的,而是由运行 emit 的线程运行的。在此线程上,没有处理程序可以处理 take 引发的控制异常,从而导致错误。